import { Subject } from 'rxjs';
import {
  IPSDEEditForm,
  IPSDEWizard,
  IPSDEWizardEditForm,
  IPSDEWizardForm,
  IPSDEWizardPanel,
  IPSDEWizardStep,
} from '@ibiz/dynamic-model-api';
import { AppCtrlControllerBase } from './app-ctrl-controller-base';
import { IMobWizardPanelController, IParam, IViewStateParam, MobWizardPanelEvents } from '../../../interface';
import { AppMobWizardPanelService } from '../../../ui-core';

export class MobWizardPanelController extends AppCtrlControllerBase implements IMobWizardPanelController {
  /**
   * 移动端向导面板部件实例
   *
   * @public
   * @type { IPSDEWizardPanel }
   * @memberof MobWizardPanelController
   */
  public controlInstance!: IPSDEWizardPanel;

  /**
   * @description 初始化行为
   * @protected
   * @type {string}
   * @memberof MobWizardPanelController
   */
  protected initAction: string = '';

  /**
   * @description 完成行为
   * @protected
   * @type {string}
   * @memberof MobWizardPanelController
   */
  protected finishAction: string = '';

  /**
   * @description 当前状态
   * @private
   * @type {string}
   * @memberof MobWizardPanelController
   */
  private curState: string = '';

  /**
   * @description 当前激活步骤表单
   * @type {string}
   * @memberof MobWizardPanelController
   */
  public activeForm: string = '';

  /**
   * @description 执行过的表单
   * @type {string[]}
   * @memberof MobWizardPanelController
   */
  public historyForms: string[] = [];

  /**
   * @description 向导表单集合
   * @type {any[]}
   * @memberof MobWizardPanelController
   */
  public wizardForms: any[] = [];

  /**
   * @description 向导步骤集合
   * @type {any[]}
   * @memberof MobWizardPanelController
   */
  public steps: any[] = [];

  /**
   * @description 步骤标识集合
   * @type {IParam}
   * @memberof MobWizardPanelController
   */
  public stepTags: IParam = {};

  /**
   * @description 步骤行为集合
   * @type {IParam}
   * @memberof MobWizardPanelController
   */
  public stepActions: IParam = {};

  /**
   * @description 向导表单参数
   * @type {IParam}
   * @memberof MobWizardPanelController
   */
  public formParam: IParam = {};

  /**
   * @description FormLoad是否被阻塞
   * @private
   * @type {boolean}
   * @memberof MobWizardPanelController
   */
  private hasFormLoadBlocked: boolean = false;

  /**
   * @description 视图状态订阅对象
   * @type {Subject<IViewStateParam>}
   * @memberof MobWizardPanelController
   */
  public wizardState: Subject<IViewStateParam> = new Subject();

  /**
   * @description 部件模型数据加载
   * @memberof MobWizardPanelController
   */
  public async ctrlModelLoad() {
    await super.ctrlModelLoad();
    if (!App.isPreviewMode()) {
      this.ctrlService = new AppMobWizardPanelService(this.controlInstance);
      await this.ctrlService.loaded();
    }
    const wizard = this.controlInstance.getPSDEWizard();
    if (wizard) {
      const wizardForms: IPSDEWizardForm[] = wizard.getPSDEWizardForms() || [];
      for (const form of wizardForms) {
        await form.fill();
        await form.getPSDEWizardStep()?.fill();
      }
    }
    this.initActiveForm();
  }

  /**
   * @description 部件基础数据初始化
   * @memberof MobWizardPanelController
   */
  public ctrlBasicInit() {
    super.ctrlBasicInit();
    this.initAction = this.controlInstance.getInitPSControlAction()?.getPSAppDEMethod?.()?.codeName || 'Get';
    this.finishAction = this.controlInstance.getFinishPSControlAction()?.getPSAppDEMethod?.()?.codeName || 'Update';
  }

  /**
   * @description 初始化激活表单
   * @protected
   * @memberof MobWizardPanelController
   */
  protected initActiveForm() {
    const wizard: IPSDEWizard | null = this.controlInstance.getPSDEWizard();
    const wizardForms: Array<IPSDEWizardForm> = wizard?.getPSDEWizardForms() || [];
    if (wizard && wizardForms.length > 0) {
      const firstForm: IPSDEWizardForm = wizardForms.find((form: IPSDEWizardForm) => {
        return form.firstForm;
      }) as IPSDEWizardForm;
      this.activeForm = `${this.controlInstance.name}_form_${firstForm.formTag?.toLowerCase()}`;
    }
  }

  /**
   * @description 部件初始化
   * @memberof MobWizardPanelController
   */
  public ctrlInit() {
    super.ctrlInit();
    this.regFormActions();
    if (this.activeForm) {
      this.historyForms.push(this.activeForm);
    }
    if (this.viewState) {
      this.viewStateEvent = this.viewState.subscribe(({ tag, action, data }: any) => {
        if (!Object.is(tag, this.name)) {
          return;
        }
        if (Object.is('load', action)) {
          this.doInit(data);
        }
      });
    }
  }

  /**
   * @description 部件挂载
   * @param {*} [args] 额外参数
   * @memberof MobWizardPanelController
   */
  public ctrlMounted(args?: any) {
    super.ctrlMounted(args);
    this.controlInstance.getPSDEEditForms()?.forEach((form: IPSDEEditForm) => {
      this.mountedMap.set(form.name, false);
    });
  }

  /**
   * @description 注册表单步骤行为
   * @protected
   * @memberof MobWizardPanelController
   */
  protected regFormActions() {
    const wizard: IPSDEWizard | null = this.controlInstance.getPSDEWizard();
    const wizardForms: Array<IPSDEWizardForm> = wizard?.getPSDEWizardForms() || [];
    const wizardSteps: Array<IPSDEWizardStep> = wizard?.getPSDEWizardSteps() || [];
    if (wizard && wizardForms.length > 0) {
      wizardForms.forEach((stepForm: IPSDEWizardForm) => {
        const formName = `${this.controlInstance.name}_form_${stepForm.formTag?.toLowerCase()}`;
        const editForm: IPSDEWizardEditForm = (this.controlInstance.getPSDEEditForms() || []).find(
          (form: IPSDEEditForm) => {
            return form.name === formName;
          },
        ) as IPSDEWizardEditForm;
        const action = {
          loadAction: editForm?.getGetPSControlAction()?.actionName || 'Get',
          preAction: editForm?.getGoBackPSControlAction()?.actionName,
          saveAction: editForm?.getUpdatePSControlAction()?.actionName || 'Update',
          actions: stepForm.getStepActions() || [],
        };
        this.regFormAction(
          formName,
          action,
          this.getStepTag(wizardSteps, stepForm?.getPSDEWizardStep()?.stepTag as string),
        );
      });
    }
    if (wizardSteps.length > 0) {
      wizardSteps.forEach((step: IPSDEWizardStep) => {
        this.steps.push({
          tag: step.stepTag,
          title: step.title,
          subTitle: step.subTitle,
          titleLanResTag: step.getTitlePSLanguageRes()?.lanResTag,
          subTitleLanResTag: step.getSubTitlePSLanguageRes()?.lanResTag,
          className: step.getTitlePSSysCss?.()?.cssName,
          icon: step.getPSSysImage?.()?.cssClass
        })
      });
    }
  }

  /**
   * 注册表单步骤行为
   *
   * @memberof WizardPanelControlBase
   */
  public regFormAction(name: string, actionParams: any, stepTag: any) {
    this.stepActions[name] = actionParams;
    this.stepTags[name] = stepTag;
    this.wizardForms.push(name);
  }

  /**
   * @description 获取步骤标识
   * @param {Array<any>} wizardSteps
   * @param {string} tag
   * @return {*}
   * @memberof MobWizardPanelController
   */
  public getStepTag(wizardSteps: Array<any>, tag: string) {
    if (wizardSteps && wizardSteps.length > 0 && tag) {
      const curStep: any = wizardSteps.find((step: any) => {
        return step.stepTag === tag;
      });
      return curStep.stepTag || tag;
    } else {
      return tag;
    }
  }

  /**
   * @description 执行初始化
   * @protected
   * @param {*} data 数据
   * @memberof MobWizardPanelController
   */
  protected doInit(opt: IParam = {}) {
    const arg: any = { ...opt };
    Object.assign(arg, { viewParam: this.viewParam });
    let tempContext: any = JSON.parse(JSON.stringify(this.context));
    this.onControlRequset('doInit', tempContext, arg);
    const post: Promise<any> = this.ctrlService.init(this.initAction, tempContext, arg, this.showBusyIndicator);
    post.then((response: any) => {
      this.onControlResponse('doInit', response);
      if (response && response.status === 200) {
        this.formParam = response.data;
        if (response.data[this.appDeCodeName.toLowerCase()]) {
          Object.assign(this.context, {
            [this.appDeCodeName.toLowerCase()]: response.data[this.appDeCodeName.toLowerCase()],
          });
        }
        this.formLoad();
      }
    })
    .catch((response: any) => {
      this.onControlResponse('doInit', response);
      App.getNoticeService().error(response.message);
    });
  }

  /**
   * @description 表单加载
   * @return {*}
   * @memberof MobWizardPanelController
   */
  public formLoad() {
    if (!this.mountedMap.get(this.activeForm)) {
      this.hasFormLoadBlocked = true;
      return;
    }
    if (this.activeForm) {
      this.wizardState.next({
        tag: this.activeForm,
        action: 'panelAction',
        data: { action: this.stepActions[this.activeForm].loadAction, emitAction: MobWizardPanelEvents.LOAD_SUCCESS, data: this.formParam },
      });
    }
  }

  /**
   * 上一步
   *
   * @memberof WizardPanelControlBase
   */
  public handlePrevious() {
    const length = this.historyForms.length;
    if (length > 1) {
      this.curState = 'PREV';
      if (this.stepActions[this.activeForm].preAction) {
        this.wizardState.next({
          tag: this.activeForm,
          action: 'panelAction',
          data: { action: this.stepActions[this.activeForm].preAction, emitAction: MobWizardPanelEvents.SAVE_SUCCESS, data: this.formParam },
        });
      } else {
        this.activeForm = this.historyForms[length - 1];
        setTimeout(() => {
          this.formLoad();
        }, 1);
        this.historyForms.splice(length - 1, 1);
      }
    }
  }

  /**
   * 下一步
   *
   * @memberof WizardPanelControlBase
   */
  public handleNext() {
    const Environment = App.getEnvironment();
    if (Environment && Environment.isPreviewMode) {
      return;
    }
    if (this.activeForm) {
      const form = this.ctrlRefsMap.get(this.activeForm);
      if (form && form.formValidateStatus && form.formValidateStatus instanceof Function) {
        form.formValidateStatus().then((state: boolean) => {
          if (state) {
            this.curState = 'NEXT';
            this.wizardState.next({
              tag: this.activeForm,
              action: 'panelAction',
              data: { action: this.stepActions[this.activeForm].saveAction, emitAction: MobWizardPanelEvents.SAVE_SUCCESS, data: this.formParam },
            });
          } else {
            App.getNoticeService().error('值规则校验异常');
          }
        }).catch((error: any) => {
          App.getNoticeService().error(error);
        })
      }
    }
  }

  /**
   * 完成
   *
   * @memberof WizardPanelControlBase
   */
  public handleFinish() {
    if (this.activeForm) {
      const form = this.ctrlRefsMap.get(this.activeForm);
      if (form && form.formValidateStatus && form.formValidateStatus instanceof Function) {
        form.formValidateStatus().then((state: boolean) => {
          console.log(this.stepActions[this.activeForm].saveAction, this.formParam);
          if (state) {
            this.curState = 'FINISH';
            this.wizardState.next({
              tag: this.activeForm,
              action: 'panelAction',
              data: { action: this.stepActions[this.activeForm].saveAction, emitAction: MobWizardPanelEvents.SAVE_SUCCESS, data: this.formParam },
            });
          } else {
            App.getNoticeService().error('值规则校验异常');
          }
        }).catch((error: any) => {
          App.getNoticeService().error(error);
        })
      }
    }
  }

  /**
   * 完成行为
   *
   * @memberof WizardPanelControlBase
   */
  public doFinish() {
    let arg: any = {};
    Object.assign(arg, this.formParam);
    Object.assign(arg, { viewParam: this.viewParam });
    let tempContext: any = JSON.parse(JSON.stringify(this.context));
    this.onControlRequset('doFinish', tempContext, arg);
    const post: Promise<any> = this.ctrlService.finish(this.finishAction, tempContext, arg, this.showBusyIndicator);
    post.then((response: any) => {
      this.onControlResponse('doFinish', response);
      if (response && response.status === 200) {
        const data = response.data;
        const uiDataParams = this.getUIDataParam();
        Object.assign(uiDataParams, { data: data });
        this.ctrlEvent(MobWizardPanelEvents.FINISH, uiDataParams);
        App.getCenterService().notifyMessage(this.appDeCodeName, 'appRefresh', data);
      }
    })
    .catch((response: any) => {
      this.onControlResponse('doFinish', response);
      App.getNoticeService().error(response.message);
    });
  }

  /**
   * 获取下一步向导表单
   *
   * @memberof WizardPanelControlBase
   */
  public getNextForm() {
    if (this.formParam && this.formParam['srfnextform']) {
      return `${this.controlInstance.name}_form_${this.formParam['srfnextform'].toLowerCase()}`;
    } else {
      let index = this.wizardForms.indexOf(this.activeForm);
      if (index >= 0) {
        if (this.wizardForms[index + 1]) {
          return this.wizardForms[index + 1];
        }
      }
      return undefined;
    }
  }

  /**
   * @description 向导表单加载完成
   * @param {string} name 向导表单名称
   * @param {*} args 数据
   * @memberof MobWizardPanelController
   */
  public wizardPanelFormLoad(name: string, args: any) {
    if (args) {
      Object.assign(this.formParam, args);
    }
  }

  /**
   * 向导表单保存完成
   *
   * @param {string} name 向导表单名称
   * @param {*} args 数据
   * @memberof WizardPanelControlBase
   */
  public wizardPanelFormSave(name: string, args: any) {
    Object.assign(this.formParam, args);
    if (Object.is(this.curState, 'NEXT')) {
      this.historyForms.push(name);
      if (this.getNextForm()) {
        this.activeForm = this.getNextForm();
        setTimeout(() => {
          this.formLoad();
        }, 1);
      } else {
        this.doFinish();
      }
    } else if (Object.is(this.curState, 'PREV')) {
      const length = this.historyForms.length;
      if (length > 1) {
        this.activeForm = this.historyForms[length - 1];
        setTimeout(() => {
          this.formLoad();
        }, 1);
        this.historyForms.splice(length - 1, 1);
      }
    } else if (Object.is(this.curState, 'FINISH')) {
      this.doFinish();
    }
  }

  /**
   * @description 处理部件事件
   * @param {string} controlname 部件名称
   * @param {string} action 行为
   * @param {*} data 数据
   * @memberof MobWizardPanelController
   */
  public handleCtrlEvent(controlname: string, action: string, data: any) {
    switch (action) {
      case MobWizardPanelEvents.MOUNTED:
        this.setIsMounted(controlname, data);
        if (this.hasFormLoadBlocked) {
          this.formLoad();
          this.hasFormLoadBlocked = false;
        }
        break;
      case MobWizardPanelEvents.SAVE_SUCCESS:
        this.wizardPanelFormSave(controlname, data);
        break;
      case MobWizardPanelEvents.LOAD_SUCCESS:
        this.wizardPanelFormLoad(controlname, data);
        break;
      default:
        super.handleCtrlEvent(controlname, action, data);
    }
  }
}
